package com.lsh.payment.core.strategy.payment;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.payment.api.model.basevo.ExceptionStatus;
import com.lsh.payment.core.constant.BusinessConstant;
import com.lsh.payment.core.exception.BusinessException;
import com.lsh.payment.core.model.payenum.AllinPayType;
import com.lsh.payment.core.model.payenum.TradeType;
import com.lsh.payment.core.strategy.config.AllinPayConfig;
import com.lsh.payment.core.strategy.config.CMBCPayConfig;
import com.lsh.payment.core.strategy.vo.allinpay.AllinpayResponse;
import com.lsh.payment.core.util.BigDecimalUtils;
import com.lsh.payment.core.util.DateUtil;
import com.lsh.payment.core.util.pay.allinpay.HttpConnectionUtil;
import com.lsh.payment.core.util.pay.allinpay.SybPayService;
import com.lsh.payment.core.util.pay.allinpay.SybUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

import static com.lsh.payment.core.constant.BusinessConstant.ALLINPAY;
import static com.lsh.payment.core.constant.BusinessConstant.STRATEGY_BEAN_NAME_PREFIX;


/**
 * Project Name: lsh-payment
 *
 * @author peter
 * @date 16/11/23
 * 北京链商电子商务有限公司
 * Package
 * desc:
 */
@Component(STRATEGY_BEAN_NAME_PREFIX + ALLINPAY)
public class AllinPayStrategy implements PayStrategy<AllinpayResponse> {

    private final static String BUILD_FLAG = "sm";

    private Logger logger = LoggerFactory.getLogger(AllinPayStrategy.class);

    @Value("${allin.notify.url}")
    private String notifyUrl;

    /**
     * 调用对应支付平台组装支付请求报文
     *
     * @param payType  传入需要的支付方式
     * @param paramMap 其他额外需要的参数
     * @return 生成的支付请求
     */
    @Override
    public AllinpayResponse generatePayParams(int payType, final Map<String, String> paramMap) {
        String prefix = "请求通联下单 ";
        logger.info("{}参数: {}", prefix, paramMap);
        BigDecimal amount = BigDecimalUtils.yuanToFen(paramMap.get("payAmount"));
        String payPaymentNo = paramMap.get("payPaymentNo");
        int channelType = Integer.parseInt(paramMap.get("channelType"));
        //组装报文

        TreeMap<String, String> params = new TreeMap<>();
        params.put("cusid", AllinPayConfig.CUS_ID);
        params.put("appid", AllinPayConfig.APP_ID);
        params.put("version", "11");
        params.put("trxamt", amount.toString());
        params.put("reqsn", payPaymentNo);
        int mis = DateUtil.minsForPay(new Date());
        String validtime;
        if (mis >= 360) {
            validtime = "360";
        } else if (mis <= 30) {
            validtime = "30";
        } else {
            validtime = String.valueOf(mis);
        }
        params.put("validtime", validtime);

        String buildFlag = BUILD_FLAG;

        if (channelType == TradeType.ALLINWXSM.getCode()) {
            params.put("paytype", AllinPayType.WXSM.getCode());
            params.put("notify_url", notifyUrl);
        } else if (channelType == TradeType.ALLINALISM.getCode()) {
            params.put("paytype", AllinPayType.ALISM.getCode());
            params.put("notify_url", notifyUrl);
        } else if (channelType == TradeType.ALLINWXBSM.getCode()) {
            params.put("limit_pay", "no_credit");
            params.put("authcode", paramMap.get("authcode"));
            buildFlag = "code";
        } else if (channelType == TradeType.ALLINALIBSM.getCode()) {
            params.put("limit_pay", "no_credit");
            params.put("authcode", paramMap.get("authcode"));
            buildFlag = "code";
        }

        params.put("randomstr", SybUtil.getValidatecode(8));
        params.put("body", AllinPayConfig.GOODS_NAME);

        String method;
        if (buildFlag.equals(BUILD_FLAG)) {
            method = AllinPayConfig.PAY_NATIVE;
        } else {
            method = AllinPayConfig.PAY_BSM;
        }
        HttpConnectionUtil http = new HttpConnectionUtil(AllinPayConfig.PAY_BASE + method);
        Map<String, String> map;
        String result;
        try {
            http.init();

            params.put("sign", SybUtil.sign(params, AllinPayConfig.KEY));

            logger.info("{} 下单参数 {}", prefix, JSON.toJSONString(params));

            byte[] bys = http.postParams(params, true);
            result = new String(bys, "UTF-8");

            logger.info("{} 返回结果 {}", prefix, result);
            map = SybPayService.handleResult(result);

        } catch (BusinessException e) {
            e.printStackTrace();
            throw new BusinessException(e.getCode(), e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ExceptionStatus.E2001005.getCode(), ExceptionStatus.E2001005.getMessage());
        }

        if (buildFlag.equals(BUILD_FLAG)) {
            return this.buildRsp(map, result, payPaymentNo);
        } else {
            return this.buildCodeRsp(map, result, payPaymentNo);
        }

    }


    /**
     * 通联下单返回值
     *
     * @param resMap 返回结果
     * @return 支付平台返回结果
     */
    private AllinpayResponse buildRsp(Map<String, String> resMap, String resultStr, String payPaymentNo) {

        AllinpayResponse response = new AllinpayResponse();
        response.setCode(BusinessConstant.PAY_REQUEST_FAIL);
        response.setMsg(BusinessConstant.PAY_REQUEST_FAIL_MESSAGE);

        logger.info("支付流水号 {} callRsp = {}", payPaymentNo, JSON.toJSONString(resMap));

        String result = resMap.get("trxstatus");
        if (StringUtils.isNotBlank(result) && result.equals(CMBCPayConfig.TRADE_STATE_SUCCESS)) {
            response = JSON.parseObject(resultStr.toString(), AllinpayResponse.class);

            response.setCode(BusinessConstant.PAY_REQUEST_SUCCESS);
            JSONObject resResult = new JSONObject();
            resResult.put("qrcode", response.getPayinfo());
            resResult.put("out_trade_no", payPaymentNo);
            response.setMsg(resResult.toJSONString());

        } else {
            response.setCode(BusinessConstant.PAY_REQUEST_FAIL);
            response.setMsg(resMap.get("errmsg"));
            //加下邮件预警
//            PayBaseService.monitor(PayChannel.QFPAY.getName(), "钱方返回:" + resMap.get("result") + jsonRet.getString("desc"),payPaymentNo);
        }

        logger.info("请求通联支付,支付流水," + payPaymentNo + "返回:" + JSON.toJSONString(response));
        return response;
    }

    /**
     * 通联下单返回值
     *
     * @param resMap 返回结果
     * @return 支付平台返回结果
     */
    private AllinpayResponse buildCodeRsp(Map<String, String> resMap, String resultStr, String payPaymentNo) {

        AllinpayResponse response = new AllinpayResponse();
        response.setCode(BusinessConstant.PAY_REQUEST_FAIL);
        response.setMsg(BusinessConstant.PAY_REQUEST_FAIL_MESSAGE);

        logger.info("支付流水号 {} callRsp = {}", payPaymentNo, JSON.toJSONString(resMap));

        String result = resMap.get("trxstatus");
        if (StringUtils.isNotBlank(result) && result.equals(CMBCPayConfig.TRADE_STATE_SUCCESS)) {
            response = JSON.parseObject(resultStr.toString(), AllinpayResponse.class);

            response.setCode(BusinessConstant.PAY_REQUEST_SUCCESS);
            JSONObject resResult = new JSONObject();
            resResult.put("out_trade_no", payPaymentNo);
            resResult.put("trxstatus", resMap.get("trxstatus"));
            resResult.put("trxmessage", resMap.get("errmsg"));
            resResult.put("acct", resMap.get("acct"));
            response.setAcct(resMap.get("acct"));
            response.setMsg(resResult.toJSONString());

        } else {
            response.setCode(BusinessConstant.PAY_REQUEST_FAIL);
            com.alibaba.fastjson.JSONObject resResult = new com.alibaba.fastjson.JSONObject();
            resResult.put("out_trade_no", payPaymentNo);
            resResult.put("trxstatus", resMap.get("trxstatus"));
            resResult.put("trxmessage", resMap.get("errmsg"));
            resResult.put("acct", resMap.get("acct"));
            response.setAcct(resMap.get("acct"));
            response.setMsg(resResult.toJSONString());
            //加下邮件预警
//            PayBaseService.monitor(PayChannel.QFPAY.getName(), "钱方返回:" + resMap.get("result") + jsonRet.getString("desc"),payPaymentNo);
        }

        logger.info("请求通联支付,支付流水," + payPaymentNo + "返回:" + JSON.toJSONString(response));
        return response;
    }
}
